import Glibc
// import Foundation

class Timer {
    private let CLOCK_REALTIME = 0
    private var start_timespec = timespec()
    private var end_timespec = timespec()
    private var time_spec = timespec()
    func start() {
        clock_gettime(Int32(CLOCK_REALTIME),&start_timespec)
    }
    
    func stop() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&end_timespec)
        let start_time = Double(start_timespec.tv_sec * 1_000_000 + start_timespec.tv_nsec / 1_000)
        let end_time = Double(end_timespec.tv_sec * 1_000_000 + end_timespec.tv_nsec / 1_000)
        let time = end_time - start_time
        return time / 1_000
    }
    func getTime() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&time_spec)
        return Double(time_spec.tv_sec * 1_000_000 + time_spec.tv_nsec / 1_000)
    }
}

let timer = Timer()
var global = 0

func runBitOp1() -> Int {
    var res = 0
    let count = 6000000
    let resources: [Int] = [12, 43, 56, 76, 89, 54, 45, 32, 35, 47, 46, 44, 21, 37, 84]
    timer.start()
    let resourcesLength = resources.count - 1
    for i in 0..<count {
        let bi3b = 0xE994;
        let b = resources[(i & res) & resourcesLength];
               res += 3 & (bi3b >> ((b << 1) & 14));
               res += 3 & (bi3b >> ((b >> 2) & 14));
               res += 3 & (bi3b >> ((b >> 5) & 6));
    }
    let time = timer.stop()
    print(res)
    // assert(res == 8, "res should be equal to 8")
    print("Numerical Calculation - RunBitOp1:\t"+String(time)+"\tms");
    return Int(time)
}

func runBitOp2() -> Int {
    var res = 0;
    timer.start()
    for x in 0..<6000000 {
        let b = x
        var m = 1, c = 0
        while m < 0x100 {
            if (b & m) != 0 {
                c += 1
            }
            m <<= 1
        }
        res += c
    }
    let time = timer.stop()
    print(res)
    // assert(res == 8, "res should be equal to 8")
    print("Numerical Calculation - RunBitOp2:\t"+String(time)+"\tms");
    return Int(time)
}

func runBitOp3() -> Int {
    var res = 0;
    timer.start()
    for y in 0..<6000000 {
        var x = y
        var r = 0
        while (x != 0) {
            x &= x - 1
            r += 1
        }
        res += r
    }
    let time = timer.stop()
    print(res)    
    print("Numerical Calculation - RunBitOp3:\t"+String(time)+"\tms");
    return Int(time)
} 

func runBitOp4() -> Int {
	var results = [3, 53, 76, 37, 82, 23, 66, 17, 82, 43, 77, 93, 28, 24, 85]
	let resources = [12, 43, 56, 76, 89, 54, 45, 32, 35, 47, 46, 44, 21, 37, 84]
    var res = 0
    timer.start()
    let resultsLength = results.count - 1
    let resourcesLength = resources.count - 1
    for i in 0..<6000000 {
		res |= ~(1 << (resources[i & resourcesLength] ^ 31));
    }
    let time = timer.stop()
    print(res)
    print("Numerical Calculation - RunBitOp4:\t"+String(time)+"\tms");
    return Int(time)
}


_ = runBitOp1()
_ = runBitOp2()
_ = runBitOp3()
_ = runBitOp4()
print("Bitops Is End , global value is \(global)")
// print(runBitOp1())

// print(runBitOp2())

// print(runBitOp3())

// print(runBitOp4())
